diff options
Diffstat (limited to 'src/routes/projects/[projectId]/routine/[routineId]')
| -rw-r--r-- | src/routes/projects/[projectId]/routine/[routineId]/+page.svelte | 87 |
1 files changed, 8 insertions, 79 deletions
diff --git a/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte b/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte index bcdca79..ab2644d 100644 --- a/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte +++ b/src/routes/projects/[projectId]/routine/[routineId]/+page.svelte @@ -1,5 +1,6 @@ <script lang="ts"> import { enhance } from '$app/forms'; + import HealthChart from '$lib/components/HealthChart.svelte'; import ScoreBadge from '$lib/components/ScoreBadge.svelte'; import StatusBadge from '$lib/components/StatusBadge.svelte'; import { @@ -7,21 +8,17 @@ parseIntervalToDays, computeHealthSeries, } from '$lib/shared/routine-metrics'; - let { data, form } = $props(); - let name = $state(''); let frequency = $state(''); let description = $state(''); let note = $state(''); let saved = $state(false); - $effect(() => { name = data.routine.name; frequency = `${data.routine.frequencyDays}d`; description = data.routine.description; }); - $effect(() => { if (form?.success && form?.type === 'edit') { saved = true; @@ -29,9 +26,7 @@ return () => clearTimeout(t); } }); - const frequencyDays = $derived(parseIntervalToDays(frequency)); - const dateFormatter = new Intl.DateTimeFormat('fr-FR', { day: 'numeric', month: 'short', @@ -41,39 +36,15 @@ month: 'short', year: 'numeric', }); - const frozenAt = $derived( data.routine.archived ? Date.parse(data.routine.archivedAt ?? data.routine.createdAt) : Date.now(), ); - const series = $derived( computeHealthSeries(data.routine, data.completions, frozenAt), ); - - const PAD = 10; - const W = 800; - const H = 140; - const geometry = $derived.by(() => { - if (series.length < 2) return null; - const minT = series[0].at; - const maxT = series[series.length - 1].at; - const span = Math.max(1, maxT - minT); - const x = (t: number) => PAD + ((t - minT) / span) * (W - 2 * PAD); - const y = (h: number) => H - PAD - (h / 100) * (H - 2 * PAD); - const points = series - .map((p) => `${x(p.at).toFixed(1)},${y(p.health).toFixed(1)}`) - .join(' '); - const grid = [0, 25, 50, 75, 100].map((h) => ({ y: y(h), label: h })); - const markers = data.completions - .map((c) => { - const t = Date.parse(c.doneAt); - return t >= minT && t <= maxT ? { x: x(t), y: y(100) } : null; - }) - .filter((m): m is { x: number; y: number } => m !== null); - return { points, grid, markers }; - }); + const markers = $derived(data.completions.map((c) => Date.parse(c.doneAt))); </script> <main> @@ -159,28 +130,12 @@ <h2 class="section-title">Santé</h2> <div class="form-card chart-card"> - {#if geometry} - <svg - class="health-chart" - viewBox="0 0 {W} {H}" - preserveAspectRatio="none" - role="img" - aria-label="Évolution de la santé de la routine dans le temps" - > - {#each geometry.grid as line (line.label)} - <line - x1={PAD} - y1={line.y} - x2={W - PAD} - y2={line.y} - class="chart-grid" - /> - {/each} - <polyline points={geometry.points} class="chart-line" fill="none" /> - {#each geometry.markers as m (m.x)} - <circle cx={m.x} cy={m.y} r="4" class="chart-marker" /> - {/each} - </svg> + <HealthChart + {series} + {markers} + ariaLabel="Évolution de la santé de la routine dans le temps" + /> + {#if series.length >= 2} <div class="chart-footer"> <StatusBadge status={data.state.status} @@ -195,8 +150,6 @@ {/if} </span> </div> - {:else} - <p class="empty">Pas encore assez d'historique pour tracer la courbe.</p> {/if} </div> @@ -280,30 +233,6 @@ align-items: stretch; } - .health-chart { - width: 100%; - height: 9rem; - } - - .chart-grid { - stroke: var(--border); - stroke-width: 1; - stroke-dasharray: 2 4; - } - - .chart-line { - stroke: var(--accent); - stroke-width: 2; - stroke-linejoin: round; - stroke-linecap: round; - } - - .chart-marker { - fill: var(--success); - stroke: var(--white); - stroke-width: 1.5; - } - .chart-footer { display: flex; align-items: center; |
